use pollster::block_on;
use wgpu::{self, PipelineCompilationOptions};
use winit::{
    application::ApplicationHandler,
    event::WindowEvent,
    event_loop::{ActiveEventLoop, EventLoop},
    window::{Window, WindowId},
}; // 用于阻塞等待异步任务完成
// 定义我们的应用状态结构体
struct App<'a> {
    window: Option<Window>, // 在某些事件（如挂起）时窗口可能被销毁，故用Option
    surface: Option<wgpu::Surface<'a>>, // Surface 与窗口关联
    device: Option<wgpu::Device>, //  GPU 交互的主要接口，一个逻辑上的"连接"。通过它，你可以创建缓冲区、纹理、着色器等资源。
    queue: Option<wgpu::Queue>, // 是向 GPU 提交命令（如渲染指令）的通道。命令被提交到队列后，由 GPU 异步执行。
    config: Option<wgpu::SurfaceConfiguration>, // Surface 的配置，定义了其格式、大小等属性
    render_pipeline: Option<wgpu::RenderPipeline>, // 渲染管线，定义了渲染过程中的各个阶段和状态
}
impl<'a> ApplicationHandler for App<'a> {
    // 当应用恢复时被调用（例如程序启动或从后台唤醒）
    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
        // 仅在窗口尚未创建时创建
        if self.window.is_none() {
            // 创建窗口属性
            let window_attributes = Window::default_attributes().with_title("我的第一个 Wgpu 窗口");
            // 创建窗口
            let window = event_loop.create_window(window_attributes).unwrap();
            self.window = Some(window);

            // It's safe to unwrap here because we just set self.window above
            let (surface, device, queue, config, render_pipeline) =
                block_on(Self::init_wgpu(self.window.as_ref().unwrap()));
            // 使用 std::mem::transmute 进行安全的生命周期转换
            // 由于surface的生命周期与window绑定，而window由App持有，
            // 所以可以安全地存储为与App相同的生命周期
            self.surface = Some(unsafe { std::mem::transmute(surface) });
            self.device = Some(device);
            self.queue = Some(queue);
            self.config = Some(config);
            self.render_pipeline = Some(render_pipeline);
        }
    }
    fn exiting(&mut self, event_loop: &ActiveEventLoop) {
        println!("应用即将退出");
        self.surface = None; // 销毁 Surface
        self.window = None; // 销毁窗口
        event_loop.exit(); // 确保事件循环退出
    }
    // 处理窗口事件，如关闭、按键等
    fn window_event(
        &mut self,
        event_loop: &ActiveEventLoop,
        _window_id: WindowId,
        event: WindowEvent,
    ) {
        match event {
            // 处理窗口关闭请求
            WindowEvent::CloseRequested => {
                println!("窗口关闭请求被接收");
                event_loop.exit(); // 退出事件循环，结束程序
            }
            // 处理键盘事件
            WindowEvent::KeyboardInput { event, .. } => {
                if event.logical_key
                    == winit::keyboard::Key::Named(winit::keyboard::NamedKey::Escape)
                {
                    println!("ESC 键被按下");
                    event_loop.exit();
                } else {
                    println!("其他键被按下: {:?}", event);
                }
            }
            // 处理窗口大小调整
            WindowEvent::Resized(new_size) => {
                println!("窗口被调整大小: {:?}", new_size);
                // 更新 Wgpu 的 Surface 配置以适应新大小
                if let (Some(device), Some(surface), Some(config)) =
                    (&self.device, &self.surface, &mut self.config)
                {
                    if new_size.width > 0 && new_size.height > 0 {
                        config.width = new_size.width;
                        config.height = new_size.height;
                        surface.configure(device, config);
                    }
                }
            }
            WindowEvent::Focused(flag) => {
                if flag {
                    println!("窗口获得焦点");
                } else {
                    println!("窗口失去焦点");
                }
            }
            _ => (),
        }
    }
    // 在事件循环准备等待新事件时调用（适合用于渲染）
    fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
        self.render();
    }
}

impl<'a> App<'a> {
    // 默认值
    fn default() -> Self {
        Self {
            window: None,
            surface: None,
            device: None,
            queue: None,
            config: None,
            render_pipeline: None,
        }
    }
    async fn init_wgpu(
        window: &Window,
    ) -> (
        wgpu::Surface<'_>,
        wgpu::Device,
        wgpu::Queue,
        wgpu::SurfaceConfiguration,
        wgpu::RenderPipeline,
    ) {
        // 1. 创建实例 (Instance)
        let instance = wgpu::Instance::default();

        // 2. 创建表面 (Surface)
        let surface = unsafe { instance.create_surface(window) }.unwrap();

        // 3. 请求适配器 (Adapter)
        // 它代表了系统中的一个物理 GPU（或软件渲染器）。你可以通过它查询硬件的功能和限制。初始化时，我们通常请求一个与创建的 Surface 兼容的适配器。
        let adapter = instance
            .request_adapter(&wgpu::RequestAdapterOptions {
                power_preference: wgpu::PowerPreference::default(),
                compatible_surface: Some(&surface),
                force_fallback_adapter: false,
            })
            .await
            .expect("Failed to find an appropriate adapter.");

        // 4. 请求逻辑设备和命令队列 (Device & Queue)
        // 是向 GPU 提交命令（如渲染指令）的通道。命令被提交到队列后，由 GPU 异步执行。
        // 设备代表了 GPU 的逻辑抽象，它包含了 GPU 的资源（如缓冲区、纹理、着色器等）。我们通过适配器请求一个设备，并通过它创建命令队列。
        let (device, queue) = adapter
            .request_device(&wgpu::DeviceDescriptor {
                label: None,                                // 设备标签
                memory_hints: wgpu::MemoryHints::default(), // 针对桌面环境使用默认内存限制
                trace: wgpu::Trace::default(),              // 不启用追踪
                required_features: wgpu::Features::empty(), // 不启用任何功能
                required_limits: wgpu::Limits::default(),   // 针对桌面环境使用默认限制
            })
            .await
            .expect("Failed to create device.");

        // 5. 配置表面 (SurfaceConfiguration)
        // 这个配置对象定义了 Surface 如何被使用，包括像素格式、大小和呈现模式。在创建 Surface 后以及窗口大小改变时，都必须调用 surface.configure(&device, &config) 来应用配置。
        let surface_caps = surface.get_capabilities(&adapter);
        let config = wgpu::SurfaceConfiguration {
            usage: wgpu::TextureUsages::RENDER_ATTACHMENT, // 表面用于渲染附件
            format: surface_caps.formats[0],               // 使用适配器支持的第一个格式
            width: window.inner_size().width,
            desired_maximum_frame_latency: 2, // 使用默认的最大帧延迟
            height: window.inner_size().height,
            present_mode: surface_caps.present_modes[0], // 使用适配器支持的第一个呈现模式
            alpha_mode: surface_caps.alpha_modes[0],     // 使用适配器支持的第一个alpha模式
            view_formats: vec![],
        };
        surface.configure(&device, &config);

        let render_pipeline = {
            let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
                label: Some("Shader"),
                source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
            });
            let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
                label: Some("Render Pipeline Layout"),
                bind_group_layouts: &[],
                push_constant_ranges: &[],
            });
            device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
                label: Some("Render Pipeline"),
                layout: Some(&pipeline_layout),
                cache : None,
                vertex: wgpu::VertexState {
                    module: &shader,
                    compilation_options: PipelineCompilationOptions::default(),
                    entry_point: Some("vs_main"),
                    buffers: &[],
                },
                fragment: Some(wgpu::FragmentState {
                    module: &shader,
                    compilation_options: PipelineCompilationOptions::default(),
                    entry_point: Some("fs_main"),
                    targets: &[Some(wgpu::ColorTargetState {
                        format: config.format,
                        blend: Some(wgpu::BlendState::REPLACE),
                        write_mask: wgpu::ColorWrites::ALL,
                    })],
                }),
                primitive: wgpu::PrimitiveState {
                    topology: wgpu::PrimitiveTopology::TriangleList,
                    strip_index_format: None,
                    front_face: wgpu::FrontFace::Ccw,
                    cull_mode: Some(wgpu::Face::Back),
                    polygon_mode: wgpu::PolygonMode::Fill,
                    unclipped_depth: false,
                    conservative: false,
                },
                depth_stencil: None,
                multisample: wgpu::MultisampleState {
                    count: 1,
                    mask: !0,
                    alpha_to_coverage_enabled: false,
                },
                multiview: None,
            })
        };
        (surface, device, queue, config, render_pipeline)
    }
    fn render(self: &mut Self) {
        // 渲染逻辑代码
        print!("渲染一帧\n");
        if let (Some(surface), Some(device), Some(queue), Some(config), Some(render_pipeline)) = (
            &self.surface, &self.device, &self.queue, &self.config, &self.render_pipeline
        ) {
            let frame = surface.get_current_texture().expect("Failed to acquire next swap chain texture");
            let view = frame.texture.create_view(&wgpu::TextureViewDescriptor::default());
            
            let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
                label: Some("Render Encoder"),
            });
            
            {
                let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
                    label: Some("Render Pass"),
                    color_attachments: &[Some(wgpu::RenderPassColorAttachment {
                        view: &view,
                        depth_slice: None,
                        resolve_target: None,
                        ops: wgpu::Operations {
                            load: wgpu::LoadOp::Clear(wgpu::Color {
                                r: 0.1,
                                g: 0.2,
                                b: 0.3,
                                a: 1.0,
                            }),
                            store: wgpu::StoreOp::Store,
                        },
                    })],
                    depth_stencil_attachment: None,
                    occlusion_query_set: None,
                    timestamp_writes: None,
                });
                
                render_pass.set_pipeline(render_pipeline);
                render_pass.draw(0..3, 0..1);
            }
            
            queue.submit(std::iter::once(encoder.finish()));
            frame.present();
        }
    }
}
fn main() {
    // 创建事件循环
    let event_loop = EventLoop::new().unwrap();

    // 创建应用状态
    let mut app = App::default();

    // 运行事件循环
    event_loop.run_app(&mut app).unwrap();
}
